home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / sys_win.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-27  |  13.0 KB  |  667 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // sys_win.h
  21.  
  22. #include "../qcommon/qcommon.h"
  23. #include "winquake.h"
  24. #include "resource.h"
  25. #include <errno.h>
  26. #include <float.h>
  27. #include <fcntl.h>
  28. #include <stdio.h>
  29. #include <direct.h>
  30. #include <io.h>
  31. #include <conio.h>
  32. #include "../win32/conproc.h"
  33.  
  34. #define MINIMUM_WIN_MEMORY    0x0a00000
  35. #define MAXIMUM_WIN_MEMORY    0x1000000
  36.  
  37. //#define DEMO
  38.  
  39. qboolean s_win95;
  40.  
  41. int            starttime;
  42. int            ActiveApp;
  43. qboolean    Minimized;
  44.  
  45. static HANDLE        hinput, houtput;
  46.  
  47. unsigned    sys_msg_time;
  48. unsigned    sys_frame_time;
  49.  
  50.  
  51. static HANDLE        qwclsemaphore;
  52.  
  53. #define    MAX_NUM_ARGVS    128
  54. int            argc;
  55. char        *argv[MAX_NUM_ARGVS];
  56.  
  57.  
  58. /*
  59. ===============================================================================
  60.  
  61. SYSTEM IO
  62.  
  63. ===============================================================================
  64. */
  65.  
  66.  
  67. void Sys_Error (char *error, ...)
  68. {
  69.     va_list        argptr;
  70.     char        text[1024];
  71.  
  72.     CL_Shutdown ();
  73.     Qcommon_Shutdown ();
  74.  
  75.     va_start (argptr, error);
  76.     vsprintf (text, error, argptr);
  77.     va_end (argptr);
  78.  
  79.     MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
  80.  
  81.     if (qwclsemaphore)
  82.         CloseHandle (qwclsemaphore);
  83.  
  84. // shut down QHOST hooks if necessary
  85.     DeinitConProc ();
  86.  
  87.     exit (1);
  88. }
  89.  
  90. void Sys_Quit (void)
  91. {
  92.     timeEndPeriod( 1 );
  93.  
  94.     CL_Shutdown();
  95.     Qcommon_Shutdown ();
  96.     CloseHandle (qwclsemaphore);
  97.     if (dedicated && dedicated->value)
  98.         FreeConsole ();
  99.  
  100. // shut down QHOST hooks if necessary
  101.     DeinitConProc ();
  102.  
  103.     exit (0);
  104. }
  105.  
  106.  
  107. void WinError (void)
  108. {
  109.     LPVOID lpMsgBuf;
  110.  
  111.     FormatMessage( 
  112.         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  113.         NULL,
  114.         GetLastError(),
  115.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  116.         (LPTSTR) &lpMsgBuf,
  117.         0,
  118.         NULL 
  119.     );
  120.  
  121.     // Display the string.
  122.     MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
  123.  
  124.     // Free the buffer.
  125.     LocalFree( lpMsgBuf );
  126. }
  127.  
  128. //================================================================
  129.  
  130.  
  131. /*
  132. ================
  133. Sys_ScanForCD
  134.  
  135. ================
  136. */
  137. char *Sys_ScanForCD (void)
  138. {
  139.     static char    cddir[MAX_OSPATH];
  140.     static qboolean    done;
  141. #ifndef DEMO
  142.     char        drive[4];
  143.     FILE        *f;
  144.     char        test[MAX_QPATH];
  145.  
  146.     if (done)        // don't re-check
  147.         return cddir;
  148.  
  149.     // no abort/retry/fail errors
  150.     SetErrorMode (SEM_FAILCRITICALERRORS);
  151.  
  152.     drive[0] = 'c';
  153.     drive[1] = ':';
  154.     drive[2] = '\\';
  155.     drive[3] = 0;
  156.  
  157.     done = true;
  158.  
  159.     // scan the drives
  160.     for (drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++)
  161.     {
  162.         // where activision put the stuff...
  163.         sprintf (cddir, "%sinstall\\data", drive);
  164.         sprintf (test, "%sinstall\\data\\quake2.exe", drive);
  165.         f = fopen(test, "r");
  166.         if (f)
  167.         {
  168.             fclose (f);
  169.             if (GetDriveType (drive) == DRIVE_CDROM)
  170.                 return cddir;
  171.         }
  172.     }
  173. #endif
  174.  
  175.     cddir[0] = 0;
  176.     
  177.     return NULL;
  178. }
  179.  
  180. /*
  181. ================
  182. Sys_CopyProtect
  183.  
  184. ================
  185. */
  186. void    Sys_CopyProtect (void)
  187. {
  188. #ifndef DEMO
  189.     char    *cddir;
  190.  
  191.     cddir = Sys_ScanForCD();
  192.     if (!cddir[0])
  193.         Com_Error (ERR_FATAL, "You must have the Quake2 CD in the drive to play.");
  194. #endif
  195. }
  196.  
  197.  
  198. //================================================================
  199.  
  200.  
  201. /*
  202. ================
  203. Sys_Init
  204. ================
  205. */
  206. void Sys_Init (void)
  207. {
  208.     OSVERSIONINFO    vinfo;
  209.  
  210. #if 0
  211.     // allocate a named semaphore on the client so the
  212.     // front end can tell if it is alive
  213.  
  214.     // mutex will fail if semephore already exists
  215.     qwclsemaphore = CreateMutex(
  216.         NULL,         /* Security attributes */
  217.         0,            /* owner       */
  218.         "qwcl"); /* Semaphore name      */
  219.     if (!qwclsemaphore)
  220.         Sys_Error ("QWCL is already running on this system");
  221.     CloseHandle (qwclsemaphore);
  222.  
  223.     qwclsemaphore = CreateSemaphore(
  224.         NULL,         /* Security attributes */
  225.         0,            /* Initial count       */
  226.         1,            /* Maximum count       */
  227.         "qwcl"); /* Semaphore name      */
  228. #endif
  229.  
  230.     timeBeginPeriod( 1 );
  231.  
  232.     vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  233.  
  234.     if (!GetVersionEx (&vinfo))
  235.         Sys_Error ("Couldn't get OS info");
  236.  
  237.     if (vinfo.dwMajorVersion < 4)
  238.         Sys_Error ("Quake2 requires windows version 4 or greater");
  239.     if (vinfo.dwPlatformId == VER_PLATFORM_WIN32s)
  240.         Sys_Error ("Quake2 doesn't run on Win32s");
  241.     else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
  242.         s_win95 = true;
  243.  
  244.     if (dedicated->value)
  245.     {
  246.         if (!AllocConsole ())
  247.             Sys_Error ("Couldn't create dedicated server console");
  248.         hinput = GetStdHandle (STD_INPUT_HANDLE);
  249.         houtput = GetStdHandle (STD_OUTPUT_HANDLE);
  250.     
  251.         // let QHOST hook in
  252.         InitConProc (argc, argv);
  253.     }
  254. }
  255.  
  256.  
  257. static char    console_text[256];
  258. static int    console_textlen;
  259.  
  260. /*
  261. ================
  262. Sys_ConsoleInput
  263. ================
  264. */
  265. char *Sys_ConsoleInput (void)
  266. {
  267.     INPUT_RECORD    recs[1024];
  268.     int        dummy;
  269.     int        ch, numread, numevents;
  270.  
  271.     if (!dedicated || !dedicated->value)
  272.         return NULL;
  273.  
  274.  
  275.     for ( ;; )
  276.     {
  277.         if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
  278.             Sys_Error ("Error getting # of console events");
  279.  
  280.         if (numevents <= 0)
  281.             break;
  282.  
  283.         if (!ReadConsoleInput(hinput, recs, 1, &numread))
  284.             Sys_Error ("Error reading console input");
  285.  
  286.         if (numread != 1)
  287.             Sys_Error ("Couldn't read console input");
  288.  
  289.         if (recs[0].EventType == KEY_EVENT)
  290.         {
  291.             if (!recs[0].Event.KeyEvent.bKeyDown)
  292.             {
  293.                 ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
  294.  
  295.                 switch (ch)
  296.                 {
  297.                     case '\r':
  298.                         WriteFile(houtput, "\r\n", 2, &dummy, NULL);    
  299.  
  300.                         if (console_textlen)
  301.                         {
  302.                             console_text[console_textlen] = 0;
  303.                             console_textlen = 0;
  304.                             return console_text;
  305.                         }
  306.                         break;
  307.  
  308.                     case '\b':
  309.                         if (console_textlen)
  310.                         {
  311.                             console_textlen--;
  312.                             WriteFile(houtput, "\b \b", 3, &dummy, NULL);    
  313.                         }
  314.                         break;
  315.  
  316.                     default:
  317.                         if (ch >= ' ')
  318.                         {
  319.                             if (console_textlen < sizeof(console_text)-2)
  320.                             {
  321.                                 WriteFile(houtput, &ch, 1, &dummy, NULL);    
  322.                                 console_text[console_textlen] = ch;
  323.                                 console_textlen++;
  324.                             }
  325.                         }
  326.  
  327.                         break;
  328.  
  329.                 }
  330.             }
  331.         }
  332.     }
  333.  
  334.     return NULL;
  335. }
  336.  
  337.  
  338. /*
  339. ================
  340. Sys_ConsoleOutput
  341.  
  342. Print text to the dedicated console
  343. ================
  344. */
  345. void Sys_ConsoleOutput (char *string)
  346. {
  347.     int        dummy;
  348.     char    text[256];
  349.  
  350.     if (!dedicated || !dedicated->value)
  351.         return;
  352.  
  353.     if (console_textlen)
  354.     {
  355.         text[0] = '\r';
  356.         memset(&text[1], ' ', console_textlen);
  357.         text[console_textlen+1] = '\r';
  358.         text[console_textlen+2] = 0;
  359.         WriteFile(houtput, text, console_textlen+2, &dummy, NULL);
  360.     }
  361.  
  362.     WriteFile(houtput, string, strlen(string), &dummy, NULL);
  363.  
  364.     if (console_textlen)
  365.         WriteFile(houtput, console_text, console_textlen, &dummy, NULL);
  366. }
  367.  
  368.  
  369. /*
  370. ================
  371. Sys_SendKeyEvents
  372.  
  373. Send Key_Event calls
  374. ================
  375. */
  376. void Sys_SendKeyEvents (void)
  377. {
  378.     MSG        msg;
  379.  
  380.     while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  381.     {
  382.         if (!GetMessage (&msg, NULL, 0, 0))
  383.             Sys_Quit ();
  384.         sys_msg_time = msg.time;
  385.           TranslateMessage (&msg);
  386.           DispatchMessage (&msg);
  387.     }
  388.  
  389.     // grab frame time 
  390.     sys_frame_time = timeGetTime();    // FIXME: should this be at start?
  391. }
  392.  
  393.  
  394.  
  395. /*
  396. ================
  397. Sys_GetClipboardData
  398.  
  399. ================
  400. */
  401. char *Sys_GetClipboardData( void )
  402. {
  403.     char *data = NULL;
  404.     char *cliptext;
  405.  
  406.     if ( OpenClipboard( NULL ) != 0 )
  407.     {
  408.         HANDLE hClipboardData;
  409.  
  410.         if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 )
  411.         {
  412.             if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) 
  413.             {
  414.                 data = malloc( GlobalSize( hClipboardData ) + 1 );
  415.                 strcpy( data, cliptext );
  416.                 GlobalUnlock( hClipboardData );
  417.             }
  418.         }
  419.         CloseClipboard();
  420.     }
  421.     return data;
  422. }
  423.  
  424. /*
  425. ==============================================================================
  426.  
  427.  WINDOWS CRAP
  428.  
  429. ==============================================================================
  430. */
  431.  
  432. /*
  433. =================
  434. Sys_AppActivate
  435. =================
  436. */
  437. void Sys_AppActivate (void)
  438. {
  439.     ShowWindow ( cl_hwnd, SW_RESTORE);
  440.     SetForegroundWindow ( cl_hwnd );
  441. }
  442.  
  443. /*
  444. ========================================================================
  445.  
  446. GAME DLL
  447.  
  448. ========================================================================
  449. */
  450.  
  451. static HINSTANCE    game_library;
  452.  
  453. /*
  454. =================
  455. Sys_UnloadGame
  456. =================
  457. */
  458. void Sys_UnloadGame (void)
  459. {
  460.     if (!FreeLibrary (game_library))
  461.         Com_Error (ERR_FATAL, "FreeLibrary failed for game library");
  462.     game_library = NULL;
  463. }
  464.  
  465. /*
  466. =================
  467. Sys_GetGameAPI
  468.  
  469. Loads the game dll
  470. =================
  471. */
  472. void *Sys_GetGameAPI (void *parms)
  473. {
  474.     void    *(*GetGameAPI) (void *);
  475.     char    name[MAX_OSPATH];
  476.     char    *path;
  477.     char    cwd[MAX_OSPATH];
  478. #if defined _M_IX86
  479.  
  480. const char *gamename = "gamex86.dll";
  481.  
  482. #ifdef NDEBUG
  483.     const char *debugdir = "release";
  484. #else
  485.     const char *debugdir = "debug";
  486. #endif
  487.  
  488. #elif defined _M_ALPHA
  489.     const char *gamename = "gameaxp.dll";
  490.  
  491. #ifdef NDEBUG
  492.     const char *debugdir = "releaseaxp";
  493. #else
  494.     const char *debugdir = "debugaxp";
  495. #endif
  496.  
  497. #endif
  498.  
  499.     if (game_library)
  500.         Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
  501.  
  502.     // check the current debug directory first for development purposes
  503.     _getcwd (cwd, sizeof(cwd));
  504.     Com_sprintf (name, sizeof(name), "%s/%s/%s", cwd, debugdir, gamename);
  505.     game_library = LoadLibrary ( name );
  506.     if (game_library)
  507.     {
  508.         Com_DPrintf ("LoadLibrary (%s)\n", name);
  509.     }
  510.     else
  511.     {
  512. #ifdef DEBUG
  513.         // check the current directory for other development purposes
  514.         Com_sprintf (name, sizeof(name), "%s/%s", cwd, gamename);
  515.         game_library = LoadLibrary ( name );
  516.         if (game_library)
  517.         {
  518.             Com_DPrintf ("LoadLibrary (%s)\n", name);
  519.         }
  520.         else
  521. #endif
  522.         {
  523.             // now run through the search paths
  524.             path = NULL;
  525.             while (1)
  526.             {
  527.                 path = FS_NextPath (path);
  528.                 if (!path)
  529.                     return NULL;        // couldn't find one anywhere
  530.                 Com_sprintf (name, sizeof(name), "%s/%s", path, gamename);
  531.                 game_library = LoadLibrary (name);
  532.                 if (game_library)
  533.                 {
  534.                     Com_DPrintf ("LoadLibrary (%s)\n",name);
  535.                     break;
  536.                 }
  537.             }
  538.         }
  539.     }
  540.  
  541.     GetGameAPI = (void *)GetProcAddress (game_library, "GetGameAPI");
  542.     if (!GetGameAPI)
  543.     {
  544.         Sys_UnloadGame ();        
  545.         return NULL;
  546.     }
  547.  
  548.     return GetGameAPI (parms);
  549. }
  550.  
  551. //=======================================================================
  552.  
  553.  
  554. /*
  555. ==================
  556. ParseCommandLine
  557.  
  558. ==================
  559. */
  560. void ParseCommandLine (LPSTR lpCmdLine)
  561. {
  562.     argc = 1;
  563.     argv[0] = "exe";
  564.  
  565.     while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
  566.     {
  567.         while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
  568.             lpCmdLine++;
  569.  
  570.         if (*lpCmdLine)
  571.         {
  572.             argv[argc] = lpCmdLine;
  573.             argc++;
  574.  
  575.             while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
  576.                 lpCmdLine++;
  577.  
  578.             if (*lpCmdLine)
  579.             {
  580.                 *lpCmdLine = 0;
  581.                 lpCmdLine++;
  582.             }
  583.             
  584.         }
  585.     }
  586.  
  587. }
  588.  
  589. /*
  590. ==================
  591. WinMain
  592.  
  593. ==================
  594. */
  595. HINSTANCE    global_hInstance;
  596.  
  597. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  598. {
  599.     MSG                msg;
  600.     int                time, oldtime, newtime;
  601.     char            *cddir;
  602.  
  603.     /* previous instances do not exist in Win32 */
  604.     if (hPrevInstance)
  605.         return 0;
  606.  
  607.     global_hInstance = hInstance;
  608.  
  609.     ParseCommandLine (lpCmdLine);
  610.  
  611.     // if we find the CD, add a +set cddir xxx command line
  612.     cddir = Sys_ScanForCD ();
  613.     if (cddir && argc < MAX_NUM_ARGVS - 3)
  614.     {
  615.         int        i;
  616.  
  617.         // don't override a cddir on the command line
  618.         for (i=0 ; i<argc ; i++)
  619.             if (!strcmp(argv[i], "cddir"))
  620.                 break;
  621.         if (i == argc)
  622.         {
  623.             argv[argc++] = "+set";
  624.             argv[argc++] = "cddir";
  625.             argv[argc++] = cddir;
  626.         }
  627.     }
  628.  
  629.     Qcommon_Init (argc, argv);
  630.     oldtime = Sys_Milliseconds ();
  631.  
  632.     /* main window message loop */
  633.     while (1)
  634.     {
  635.         // if at a full screen console, don't update unless needed
  636.         if (Minimized || (dedicated && dedicated->value) )
  637.         {
  638.             Sleep (1);
  639.         }
  640.  
  641.         while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  642.         {
  643.             if (!GetMessage (&msg, NULL, 0, 0))
  644.                 Com_Quit ();
  645.             sys_msg_time = msg.time;
  646.             TranslateMessage (&msg);
  647.                DispatchMessage (&msg);
  648.         }
  649.  
  650.         do
  651.         {
  652.             newtime = Sys_Milliseconds ();
  653.             time = newtime - oldtime;
  654.         } while (time < 1);
  655. //            Con_Printf ("time:%5.2f - %5.2f = %5.2f\n", newtime, oldtime, time);
  656.  
  657.         //    _controlfp( ~( _EM_ZERODIVIDE /*| _EM_INVALID*/ ), _MCW_EM );
  658.         _controlfp( _PC_24, _MCW_PC );
  659.         Qcommon_Frame (time);
  660.  
  661.         oldtime = newtime;
  662.     }
  663.  
  664.     // never gets here
  665.     return TRUE;
  666. }
  667.